package com.sumainfor.common.config;

/**
 * @Author Jack Chen
 * @Create 2019-01-17 18:36
 */

import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import com.alibaba.druid.util.JdbcConstants;
import com.sumainfor.common.entity.SysUserVo;
import com.sumainfor.common.exception.TCException;
import com.sumainfor.common.util.ContextUtils;
import com.sumainfor.common.utlis.ShowSqlUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;

import java.util.List;
import java.util.Properties;

@Log4j2
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class InsertSqlInjector implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //获取sql语句
        String sql = ShowSqlUtils.getSqlByInvocation(invocation);
        if (StringUtils.isBlank(sql)) {
            return invocation.proceed();
        }

        //判断是否忽略数据权限验证
        if (ShowSqlUtils.isIgnoreAuthCheck(invocation)) {
            return invocation.proceed();
        }


        String dbType = JdbcConstants.MYSQL;
        sql = SQLUtils.format(sql, dbType);
        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);
        String action = null;
        String tableName = null;
        if (!stmtList.isEmpty()) {
            SQLStatement stmt = stmtList.get(0);
            MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
            stmt.accept(visitor);
            action = visitor.getTables().values().iterator().next().toString();
            tableName = visitor.getTables().keySet().iterator().next().getName();
        }

        if (StringUtils.isBlank(action)) {
            throw new TCException("没有读取到操作类型");
        }

        if (StringUtils.isBlank(tableName)) {
            throw new TCException("没有找到表名称");
        }

        String checkActionName = "Insert";
        if (action.equals(checkActionName)) {
            log.info("检测到插入数据操作");
            SysUserVo userVo = ContextUtils.getSysUser();
            if (userVo == null) {
                throw new TCException("没有获取到当前登录的用户 ERROR");
            }


            if (!sql.contains("areaId") && !sql.contains("deptId")) {
                String resultSql = setSql(sql, userVo);
                //包装sql后，重置到invocation中
                ShowSqlUtils.resetSql2Invocation(invocation, resultSql);
            }
        }

        return invocation.proceed();
    }

    /**
     * 更改SQL语句
     *
     * @param sql
     * @return
     */
    public String setSql(String sql, SysUserVo userVo) {
        String[] spiteSql = sql.split("VALUES");
        StringBuffer sb = new StringBuffer();

        String colSql = spiteSql[0].trim();
        String endSql = spiteSql[1].trim();

        sb.append(colSql.replaceAll("\\)", ""));
        sb.append(",areaId,deptId)");
        sb.append(" VALUES ");

        //拼接值
        sb.append(endSql.replaceAll("\\)", ""));
        sb.append(",")
                .append(userVo.getAreaId())
                .append(",")
                .append(userVo.getDeptId())
                .append(")");

        return sb.toString();
    }


    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
